#include "interrupt.h"
#include "gpio.h"

void hal_gpio_IT_init(gpio_t *gpio, 
            unsigned int pins, gpio_mode_t mode)//gpio组
{
	unsigned int i = 0;
	// 1. 使用GPIOx控制器的时钟
	RCC->MP_AHB4ENSETR = 0x7FF;
	// 2. 设置GPIO引脚为输入的功能
	for ( i = 0;i < 16; i++) {
		if (pins & (0x1 << i)) {
			break;
		}
	}
	gpio->MODER &= (~(0x3 << (i * 2)));
	gpio->MODER |= (mode << (i * 2));
}
// KEY1->PF9->EXTI9-->输入事件编号为：9
void hal_exti_IT_init(unsigned int pins,
		gpio_exti_t exti,
		exti_trigger_t trigger,input_event_t event)
{
	unsigned int i = 0;
	for ( i = 0;i < 16; i++) {
		if (pins & (0x1 << i)) {
			break;
		}
	}
	// 1. 设置PF9连接到EXTI9上   EXTI_EXTICR3[15:8] = 0x5
	switch (i / 4) {
	case 0:
		EXTI->EXTICR1 &= (~(0xFF << (i % 4 * 8)));
		EXTI->EXTICR1 |= (exti << (i % 4 * 8));
		break;	
	case 1:
		EXTI->EXTICR2 &= (~(0xFF << (i % 4 * 8)));
		EXTI->EXTICR2 |= (exti << (i % 4 * 8));
		break;
	case 2:
		EXTI->EXTICR3 &= (~(0xFF << (i % 4 * 8)));
		EXTI->EXTICR3 |= (exti << (i % 4 * 8));
		break;
	case 3:
		EXTI->EXTICR4 &= (~(0xFF << (i % 4 * 8)));
		EXTI->EXTICR4 |= (exti << (i % 4 * 8));
		break;
	}
	// 2. 设置KEY1按键为下降沿检测          EXTI_FTSR1[9] = 0x1
	if (trigger == EXTI_FALLING) {
		EXTI->FTSR1 |= (0x1 << event);
	} else {
		EXTI->RTSR1 |= (0x1 << event);
	}
	// 3. 使能EXTI中断                    EXTI_C1IMR1[9] = 0x1
	EXTI->C1IMR1 |= (0x1 << event);
}
// KEY1->PF9->EXTI9-->中断号为99
void hal_gic_IT_init(unsigned int irq_num,
		unsigned int priority) 
{
	// 1. 设置GICD层的中断使能   GICD_ISENABLER3[3] = 0x1
	GICD->ISENABLER[irq_num / 32] |= (0x1 << (irq_num % 32));
	// 2. 设置GICD层的中断优先级   GICD_IPRIORITYR24[31:27] = 自己定义 范围0-31
	GICD->IPRIORITYR[irq_num / 4] &= (~(0x1F << (irq_num % 4 * 8 + 3)));
	GICD->IPRIORITYR[irq_num / 4] |= (priority << (irq_num % 4 * 8 + 3));
	// 3. 设置GICD层中断目标分配   GICD_ITARGETSR24[25:24] = 0x1
	GICD->ITARGETSR[irq_num / 4] &= (~(0x3 << (irq_num % 4 * 8)));
	GICD->ITARGETSR[irq_num / 4] |= (0x1 << (irq_num % 4 * 8));
	// 4. 设置GICD层全局中断使能   GICD_CTLR[0] = 0x1
    GICD->CTRL |= (0x1 << 0);
    // 5. 设置GICC层中断优先级屏蔽 GICC_PMR[7:3] = 0x1F  自己也可以给其他值
    GICC->PMR |= (0x1F << 3);
	// 6. 设置GICC层全局中断使能   GICC_CTLR[0] = 0x1
	GICC->CTRL |= (0x1 << 0);
}

void hal_clear_exti_IT(exti_trigger_t trigger,input_event_t event)
{
	if (trigger == EXTI_FALLING) {
		EXTI->FPR1 |= (0x1 << event);
	} else {
		EXTI->RPR1 |= (0x1 << event);
	}
}

void hal_clear_gicc_IT(unsigned int irq_num)
{
	GICD->ICPENDR[irq_num / 32] |= (0x1 << (irq_num % 32));
}
